/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.nextsql;

import br.com.nextsql.renderizar.*;
import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Properties;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JOptionPane;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class GlobalConf {
    private static String principalDir = "./conf";
    private static String principalFile = "/principal.conf";
    private static String bancoDir = "./conf/sql/";
    private static String conexoesDir = "./conf/conexoes/";
    private static String driveDir = "./lib/driver/";
    private static String linguasDir = "./conf/linguas/";
    private static String linguasPadrao = "pt-br.lingua";
    private static String modoEncriptar = "AES";
    private static byte[] modoEncriptarChave = {85, 10, 0, -25, 68, 88, 46, 37, 107, 48, 10, -1, -37, -90, 70, -36};
    public static String getPrincipalDir() {
        return principalDir;
    }
    public static String getPrincipalFile() {
        return principalFile;
    }
    public static void criarLinguaPadrao(){
            Properties principal = lerPropriedades();
            Properties propriedades = new Properties();
            propriedades.setProperty("Lingua.Definicao", "Portugues Brasil");
            propriedades.setProperty("Texto.Modelo", "SELECT DATE_SUB(NOW(), INTERVAL 1 DAY),\n\t'Palavra' AS lit\n FROM tabelaA AS ta -- Um comentário\nWHERE `colunaA` IS NULL; #Mais comentários\nCREATE TABLE /*!32312 IF NOT EXISTS*/ tabelaB\n\t(id INT, nome VARCHAR(30) DEFAULT \"Inicio\");");
            propriedades.setProperty("ajuda", "Ajuda");
            propriedades.setProperty("arquivo", "Arquivo");
            propriedades.setProperty("bancoDados", "Banco de dados");
            propriedades.setProperty("cancelar", "Cancelar");
            propriedades.setProperty("cascata", "Cascata");
            propriedades.setProperty("conectarEm", "Conectar em");
            propriedades.setProperty("corRealce", "Cor do realce");
            propriedades.setProperty("corTexto", "Cor do texto");
            propriedades.setProperty("editar", "Editar");
            propriedades.setProperty("elementos", "Elementos");
            propriedades.setProperty("erroExisteConexao", "Já existe uma conexão com este nome.");
            propriedades.setProperty("erroNomeConexao", "Por favor cadastrar um nome para a conexão.");
            propriedades.setProperty("erroSalvarConexao", "Não foi possivel salvar o arquivo: ");
            propriedades.setProperty("erroSelecioneConexao", "Por favor selecione uma conexão para excluir.");
            propriedades.setProperty("excluir", "Excluir");
            propriedades.setProperty("exemplo", "Exemplo");
            propriedades.setProperty("fechar", "Fechar");
            propriedades.setProperty("fonte", "Fonte");
            propriedades.setProperty("fonteCores", "Fonte e cores");
            propriedades.setProperty("geral", "Geral");
            propriedades.setProperty("gerenciarConexoes", "Gerenciar conexões");
            propriedades.setProperty("italico", "Itálico");
            propriedades.setProperty("janela", "Janela");
            propriedades.setProperty("lingua", "Lingua");
            propriedades.setProperty("negrito", "Negrito");
            propriedades.setProperty("nomeConexao", "Nome da conexão");
            propriedades.setProperty("novo", "Novo");
            propriedades.setProperty("organizar", "Organizar");
            propriedades.setProperty("preferencias", "Preferências");
            propriedades.setProperty("porta", "Porta");
            propriedades.setProperty("sair", "Sair");
            propriedades.setProperty("salvar", "Salvar");
            propriedades.setProperty("salvarAbrir", "Salvar e abrir");
            propriedades.setProperty("senha", "Senha");
            propriedades.setProperty("servidor", "Servidor/IP");
            propriedades.setProperty("sobre", "Sobre");
            propriedades.setProperty("sublinhado", "Sublinhado");
            propriedades.setProperty("tabulacao", "Tabulação");
            propriedades.setProperty("tipoConexao", "Tipo de conexão");
            propriedades.setProperty("usuario", "Usuário");
            propriedades.setProperty("versao", "Versão");
        try{
            if(new File(principal.getProperty("file.linguaDir")).exists()){
                new OrdenadorProperties().OrdenarProperties(propriedades, principal.getProperty("file.linguaDir")+principal.getProperty("file.lingua"), "Arquivo de linguas:");
            }
        }catch(Exception ex){
            JOptionPane.showMessageDialog(null, ex);
        }
    }
    public static void criarPropriedades(){
        String senha = null;
        //Pasta default da aplicação; System.getProperty("user.dir");
        Properties propriedades = new Properties();
        //Setando propriedades padrão
        propriedades.setProperty("file.lingua", linguasPadrao);
        propriedades.setProperty("file.linguaDir", linguasDir);
        propriedades.setProperty("file.driverDir", driveDir);
        propriedades.setProperty("file.conexoesDir", conexoesDir);
        propriedades.setProperty("file.bancoDir", bancoDir);
        propriedades.setProperty("fonte", "Monospaced");
        propriedades.setProperty("fonte.tabulacao", "4");
        propriedades.setProperty("fonte.tamanho", "12");
        for (byte b : gerarSenha()) {
            if(senha == null){
                senha = ""+b;
            }else{
                senha += ","+b;
            }
        }
        propriedades.setProperty("senha", senha);
        try{
            if(!new File(principalDir).exists()){
                File dir = new File(principalDir);
                dir.mkdirs();
            }
            if(!new File(conexoesDir).exists()){
                File dir = new File(conexoesDir);
                dir.mkdirs();
            }
            if(!new File(linguasDir).exists()){
                File dir = new File(linguasDir);
                dir.mkdirs();
            }
            if(!new File(bancoDir).exists()){
                File dir = new File(bancoDir);
                dir.mkdirs();
            }
            if(!new File(driveDir).exists()){
                File dir = new File(driveDir);
                dir.mkdirs();
            }
            new OrdenadorProperties().OrdenarProperties(propriedades, principalDir+principalFile, "Arquivo de configuração:");
        }catch(Exception ex){
            JOptionPane.showMessageDialog(null, ex);
        }
    }
    public static void criarSQL(){
        String comandos[] = {
            "ADD",
            "AND",
            "ANY",
            "ALL",
            "ALTER",
            "AS",
            "AUTO_INCREMENT",
            "BETWEEN",
            "BY",
            "CASE",
            "CAST",
            "CHECK",
            "CREATE",
            "COLUMN",
            "DATABASE",
            "DEFAULT",
            "DELETE",
            "DISTINCT",
            "DROP",
            "END",
            "ELSE",
            "EXISTS",
            "EXPLAIN",
            "FOREIGN",
            "FROM",
            "FULL",
            "GROUP",
            "HAVING",
            "IN",
            "INDEX",
            "INNER",
            "INSERT",
            "INTO",
            "IS",
            "ISNULL",
            "JOIN",
            "KEY",
            "LEFT",
            "LIKE",
            "NOT",
            "NOTNULL",
            "NULL",
            "ON",
            "OR",
            "ORDER",
            "PRIMARY",
            "REFERENCES",
            "RENAME",
            "RIGHT",
            "SELECT",
            "SET",
            "SIMILAR",
            "SOME",
            "TABLE",
            "THEN",
            "TO",
            "TYPE",
            "UNION",
            "UNIQUE",
            "UPDATE",
            "VIEW",
            "WHEN",
            "WHERE"
        };
        String separadores[] = {
            "9", "10", "32", "40", "41", "42", "59"
        };
        String simbolos[] = {
            "!","@","%","&","*","(",")","-","+","=","{","[","^","~","]","}","|","<",",",">",".",":",";","/","?"
        };
        String aspas[] = {
            "\"(.*?)\"",
            "'(.*?)'",
            "`(.*?)`"
        };
        String comentarios[] = {
            "\\/\\*([.|\\w\\W]*?)\\*\\/",
            "\\-\\-(.*?)\n"
        };
        String funcoes[] = {
            "ABBREV",
            "ABS",
            "ACOS",
            "AGE",
            "AREA",
            "ARRAY_APPEND",
            "ARRAY_CAT",
            "ARRAY_DIMS",
            "ARRAY_LOWER",
            "ARRAY_PREPEND",
            "ARRAY_TO_ARRAY",
            "ARRAY_TO_STRING",
            "ARRAY_UPPER",
            "ASCII",
            "ASIN",
            "ATAN",
            "ATAN2",
            "AVG",
            "BIT",
            "BIT_AND",
            "BIT_LENGTH",
            "BIT_OR",
            "BOOL_AND",
            "BOOL_OR",
            "BOX",
            "BOX_INTERSECT",
            "BROADCAST",
            "BTRIM",
            "CAST",
            "CBRT",
            "CEIL",
            "CEILING",
            "CENTER",
            "CHAR_LENGTH",
            "CHARACTER_LENGTH",
            "CHR",
            "CIRCLE",
            "COALESCE",
            "CONVERT",
            "COS",
            "COT",
            "COUNT",
            "CURRENT_DATABASE",
            "CURRENT_DATE",
            "CURRENT_SCHEMA",
            "CURRENT_SCHEMAS",
            "CURRENT_SETTING",
            "CURRENT_TIME",
            "CURRENT_TIMESTAMP",
            "CURRENT_USER",
            "CURRVAL",
            "DATE_PART",
            "DATE_TRUNC",
            "DECODE",
            "DEGREES",
            "DIAMETER",
            "ENCODE",
            "EVERY",
            "EXP",
            "EXTRACT",
            "FAMILY",
            "FLOOR",
            "FORMAT_TYPE",
            "GENERATE_SERIES",
            "GET_BIT",
            "GET_BYTE",
            "HAS_DATABASE_PRIVILEGE",
            "HAS_FUNCTION_PRIVILEGE",
            "HAS_LANGUAGE_PRIVILEGE",
            "HAS_SCHEMA_PRIVILEGE",
            "HAS_TABLE_PRIVILEGE",
            "HAS_TABLESPACE_PRIVILEGE",
            "HEIGHT",
            "HOST",
            "HOSTMASK",
            "INET_CLIENT_ADDR",
            "INET_CLIENT_PORT",
            "INET_SERVER_ADDR",
            "INET_SERVER_PORT",
            "INITCAP",
            "ISCLOSED",
            "ISFINITE",
            "ISOPEN",
            "LENGTH",
            "LN",
            "LOCALTIME",
            "LOCALTIMESTAMP",
            "LOG",
            "LOWER",
            "LPAD",
            "LSEG",
            "LTRIM",
            "MASKLEN",
            "MAX",
            "MD5",
            "MIN",
            "MOD",
            "NETMASK",
            "NETWORK",
            "NEXTVAL",
            "NOW",
            "NPOINTS",
            "NULLIF",
            "OBJ_DESCRIPTION",
            "OCTET_LENGTH",
            "OVERLAY",
            "PATH",
            "PCLOSE",
            "PG_CANCEL_BACKEND",
            "PG_CLIENT_ENCODING",
            "PG_CONVERSION_IS_VISIBLE",
            "PG_GET_CONSTRAINTDEF",
            "PG_GET_EXPR",
            "PG_GET_INDEXDEF",
            "PG_GET_RULEDEF",
            "PG_GET_START_BACKUP",
            "PG_GET_STOP_BACKUP",
            "PG_GET_SERIAL_SEQUENCE",
            "PG_GET_TABLESPACE_DATABASES",
            "PG_GET_TRIGGERDEF",
            "PG_GET_USERBYID",
            "PG_GET_VIEWDEF",
            "PG_FUNCTION_IS_VISIBLE",
            "PG_OPCLASS_IS_VISIBLE",
            "PG_OPERATOR_IS_VISIBLE",
            "PG_TABLE_IS_VISIBLE",
            "PG_TYPE_IS_VISIBLE",
            "PI",
            "POINT",
            "POLYGON",
            "POPEN",
            "POSITION",
            "POWER",
            "QUOTE_IDENT",
            "QUOTE_LITERAL",
            "RADIANS",
            "RADIUS",
            "RANDOM",
            "REGEXP_REPLACE",
            "REPEAT",
            "REPLACE",
            "ROUND",
            "RPAD",
            "RTRIM",
            "SESSION_USER",
            "SET_BIT",
            "SET_BYTE",
            "SET_CONFIG",
            "SET_MASKLEN",
            "SETSEED",
            "SETVAL",
            "SIGN",
            "SIN",
            "SPLIT_PART",
            "SQRT",
            "STDDEV",
            "STRPOS",
            "SUBSTR",
            "SUBSTRING",
            "SUM",
            "TAN",
            "TEXT",
            "TIMEOFDAY",
            "TO_ASCII",
            "TO_CHAR",
            "TO_DATE",
            "TO_HEX",
            "TO_NUMBER",
            "TO_TIMESTAMP",
            "TRANSLATE",
            "TRIM",
            "TRUNC",
            "UPPER",
            "USER",
            "VARIANCE",
            "VERSION",
            "WIDTH",
            "WIDTH_BUCKET",
        };
        String ignorar[] = {
            "\\\\'",
            "\\\\\""
        };
        String txt = null;
        Properties principal = lerPropriedades();
        Properties propriedades = new Properties();
        propriedades.setProperty("Classe", "org.postgresql.Driver");
        propriedades.setProperty("Arquivo", "postgresql-9.0-connector-java.jar");
        propriedades.setProperty("Nome", "PostgreSQL");
        propriedades.setProperty("ListarBD", "SELECT datname FROM pg_database WHERE datname NOT IN ('template0','template1') ORDER BY 1;");
        propriedades.setProperty("Conexao", "jdbc:postgresql://");
        propriedades.setProperty("PastaConfig", "postgresql/");
        for (String b : comandos) {
            if(txt == null){
                txt = ""+b;
            }else{
                txt += ","+b;
            }
        }
        propriedades.setProperty("PalavrasReservadas", txt);
        txt = null;
        for (String b : separadores) {
            if(txt == null){
                txt = ""+b;
            }else{
                txt += ","+b;
            }
        }
        propriedades.setProperty("PalavrasReservadasSeparador", txt);
        txt = null;
        for (String b : simbolos) {
            if(txt == null){
                txt = ""+b;
            }else{
                txt += " "+b;
            }
        }
        propriedades.setProperty("Simbolos", txt);
        txt = null;
        for (String b : funcoes) {
            if(txt == null){
                txt = ""+b;
            }else{
                txt += ","+b;
            }
        }
        propriedades.setProperty("Funcoes", txt);
        txt = null;
        for (String b : aspas) {
            if(txt == null){
                txt = ""+b;
            }else{
                txt += " ;SEPARADOR; "+b;
            }
        }
        propriedades.setProperty("ERAspas", txt);
        txt = null;
        for (String b : ignorar) {
            if(txt == null){
                txt = ""+b;
            }else{
                txt += " ;SEPARADOR; "+b;
            }
        }
        propriedades.setProperty("Ignorar", txt);
        txt = null;
        for (String b : comentarios) {
            if(txt == null){
                txt = ""+b;
            }else{
                txt += " ;SEPARADOR; "+b;
            }
        }
        propriedades.setProperty("ERComentarios", txt);
        
        try{
            if(new File(principal.getProperty("file.bancoDir")).exists()){
                new OrdenadorProperties().OrdenarProperties(propriedades, principal.getProperty("file.bancoDir")+"postgresql.conf", "Arquivo de Bando de dados:");
            }
        }catch(Exception ex){
            JOptionPane.showMessageDialog(null, ex);
        }
        /*/Criar pasta com configurações basicas
        if(!new File(principal.getProperty("file.bancoDir")+propriedades.getProperty("PastaConfig")).exists()){
            File dir = new File(principal.getProperty("file.bancoDir")+propriedades.getProperty("PastaConfig"));
            dir.mkdirs();
        }
        /*
        Properties comentarios = new Properties();
        comentarios.setProperty("Nome", "Comentários");
        comentarios.setProperty("italico", "false");
        comentarios.setProperty("negrito", "false");
        comentarios.setProperty("sublinhado", "false");
        try{
            if(new File(principal.getProperty("file.bancoDir")).exists()){
                new OrdenadorProperties().OrdenarProperties(comentarios, principal.getProperty("file.bancoDir")+propriedades.getProperty("PastaConfig")+"comentarios.conf", "Arquivo de configuração do texto comentário:");
            }
        }catch(Exception ex){
            JOptionPane.showMessageDialog(null, ex);
        }
        */
    }
    public static String criptografar(String valor){
        try{
            SecretKeySpec chave = new SecretKeySpec(modoEncriptarChave, modoEncriptar);
            Cipher cipher = Cipher.getInstance(modoEncriptar);
            cipher.init(Cipher.ENCRYPT_MODE, chave);
            byte codificado[] = cipher.doFinal(valor.getBytes("UTF8"));
            return new BASE64Encoder().encode(codificado);
        }catch(Exception ex){
            JOptionPane.showMessageDialog(null, ex);
        }
        return null;
    }
    public static String descriptografar(String valor){
        try{
            SecretKeySpec chave = new SecretKeySpec(modoEncriptarChave, modoEncriptar);
            byte decodificando[] = new BASE64Decoder().decodeBuffer(valor);
            Cipher cipher = Cipher.getInstance(modoEncriptar);
            cipher.init(Cipher.DECRYPT_MODE, chave);
            return new String(cipher.doFinal(decodificando));
        }catch(Exception ex){
            JOptionPane.showMessageDialog(null, ex);
        }
        return null;
    }
    public static byte[] gerarSenha(){
        try{
            KeyGenerator chave = KeyGenerator.getInstance(modoEncriptar);
            return chave.generateKey().getEncoded();
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return null;
    }
    public static String limparAcentos(String texto){
        texto = texto.replaceAll("[ÂÀÁÄÃ]","A");
        texto = texto.replaceAll("[âãàáä]","a");
        texto = texto.replaceAll("[ÊÈÉË]","E");
        texto = texto.replaceAll("[êèéë]","e");
        texto = texto.replaceAll("ÎÍÌÏ","I");
        texto = texto.replaceAll("îíìï","i");
        texto = texto.replaceAll("[ÔÕÒÓÖ]","O");
        texto = texto.replaceAll("[ôõòóö]","o");
        texto = texto.replaceAll("[ÛÙÚÜ]","U");
        texto = texto.replaceAll("[ûúùü]","u");
        texto = texto.replaceAll("Ç","C");
        texto = texto.replaceAll("ç","c");
        texto = texto.replaceAll("[ýÿ]","y");
        texto = texto.replaceAll("Ý","Y");
        texto = texto.replaceAll("ñ","n");
        texto = texto.replaceAll("Ñ","N");
        texto = texto.replaceAll("['<>\\|/]","");
        return texto;
    }
    public static Properties[] lerConexoes(){
        Properties principal = lerPropriedades();
        File dir = new File(principal.getProperty("file.conexoesDir"));
        FilenameFilter fileType = new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".con");
            }
        };
        String[] dirFilhos = dir.list(fileType);
        Properties propriedades[] = new Properties[dirFilhos.length];
        if(dirFilhos.length > 0){
            for(int i=0; i<dirFilhos.length; i++){
                Properties prop = new Properties();
                try{
                    FileInputStream file = new FileInputStream(principal.getProperty("file.conexoesDir")+dirFilhos[i]);
                    prop.load(file);
                    propriedades[i] = prop;
                    file.close();
                }catch(Exception ex){}
            }
        }
        return propriedades;
    }
    public static Properties lerLingua(){
        Properties principal = lerPropriedades();
        Properties propriedades = new Properties();
        try{
            FileInputStream file = new FileInputStream(principal.getProperty("file.linguaDir")+principal.getProperty("file.lingua"));
            propriedades.load(file);
        }catch(Exception ex){}
        return propriedades;
    }
    public static Properties lerPropriedades(){
        Properties propriedades = new Properties();
        try{
            FileInputStream file = new FileInputStream(principalDir+principalFile);
            propriedades.load(file);
            int i =0;
            for (String b : propriedades.getProperty("senha").split(",")) {
                modoEncriptarChave[i] = Byte.parseByte(b);
                i++;
            }
            if(!new File(propriedades.getProperty("file.conexoesDir")).exists()){
                File dir = new File(propriedades.getProperty("file.conexoesDir"));
                dir.mkdirs();
            }
            if(!new File(propriedades.getProperty("file.linguaDir")).exists()){
                File dir = new File(propriedades.getProperty("file.linguaDir"));
                dir.mkdirs();
            }
            if(!new File(propriedades.getProperty("file.bancoDir")).exists()){
                File dir = new File(propriedades.getProperty("file.bancoDir"));
                dir.mkdirs();
            }
        }catch(Exception ex){}
        return propriedades;
    }
    public static String MD5(String texto){
        try{
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(texto.getBytes("UTF8"), 0, texto.length());
            return ""+new BigInteger(1, md.digest()).toString(16);
        }catch(Exception ex){}
        return null;
    }
    public static void verificarArquivos(){
        if(!new File(principalDir+principalFile).exists()){
            criarPropriedades();
        }
        Properties propriedades = lerPropriedades();
        if(!new File(propriedades.getProperty("file.linguaDir")+propriedades.getProperty("file.lingua")).exists()){
            criarLinguaPadrao();
        }
        if(!new File(propriedades.getProperty("file.bancoDir")+"postgresql.conf").exists()){
            criarSQL();
        }
    }
}